ggplot2(1) - 概述

R语言中的绘图系统

R语言中存在着3种不同的绘图系统:

  • base:这是最早的绘图系统,这种绘图系统非常简单,容易上手,使用plot()函数就是这个系统的,但是很难绘出比较好看的图形。后来又开发了grid绘图系统,当时开发grid绘图系统时,是为了修改base中的一些限制,从而使用绘图更为灵活。
  • lattice:中文名称是晶格,格子的意思。lattice绘图系统是建立在grid系统之上的。它有grid不具备的两个特点:①每个绘图的结果都能被保存到一个变量中,而不仅仅是绘制在屏幕上。这表明用户可以先画出一些图形,再对其进行编辑,然后再把它画出来。②可在一个格子中包含多个面板,因此可以将图形分成不同的类别,并比较各级之间的差异。
  • ggplot2:这个gg指的是grammar of graphics,这种绘图系统的目标在于把图形分解成不同的组块。

lattice绘图系统简要

lattice绘图系统中对应的plot函数是xyplot,它使用了一个公式接口来指定x和y坐标变量,绘图效果如下所示:

1
2
library(lattice)
xyplot(Turnout ~ Income, obama_vs_mccain)

它的很多参数与base系统中的基本一致,如下所示:

1
xyplot(Turnout ~ Income, obama_vs_mccain, col = "violet", pch = 20)

ggplot2绘图系统

在ggplot2绘图系统中,每个绘图都由ggplot函数创建,它的第一个参数是数据框,第二个参数是aesthetic,这个参数其实就是把x和y列变量传递给aes函数,最后再添加一个geom_这种形式的参数,让图形显示出一些点,如下所示:

1
2
library(ggplot2)
ggplot(obama_vs_mccain, aes(Income, Turnout)) + geom_point()

绘图数据集

我们用的数据集是obama_vs_mccain,这个数据集中的信息是2008年美国大选的数据,位于learningr包中,如下所示:

1
2
3
4
5
6
7
8
> head(obama_vs_mccain[1:5])
State Region Obama McCain Turnout
1 Alabama IV 38.74 60.32 61.6
2 Alaska X 37.89 59.42 68.0
3 Arizona IX 44.91 53.39 55.7
4 Arkansas VI 38.86 58.72 53.1
5 California IX 60.94 36.91 62.0
6 Colorado VIII 53.66 44.71 70.8

绘图结果如下所示:

修改绘图参数

ggplot2可以识别base中的图形系统的命令来改变点的颜色和形状,也有自己的绘图参数,现在将代码修改为以下内容:

1
2
ggplot(obama_vs_mccain, aes(Income, Turnout)) +
geom_point(color = "violet", shape = 20)

设置对数坐标

如果要将坐标以对数的形式进行设置,可以添加scale_x_log10scale_y_log10参数,参数内的参数是breaks,它表示的是意思是指定刻度值的位置,代码修改为:

1
2
3
4
ggplot(obama_vs_mccain, aes(Income, Turnout)) +
geom_point()+
scale_x_log10(breaks=seq(2e4,4e4,1e4))+
scale_y_log10(breaks=seq(50, 75, 5))

图形的分面

使用切面(facet)可以将图形分割为不同的面板,此时需要添加的函数是facet_wrap,如下所示

1
2
3
4
5
ggplot(obama_vs_mccain, aes(Income, Turnout)) +
geom_point()+
scale_x_log10(breaks=seq(2e4,4e4,1e4))+
scale_y_log10(breaks=seq(50, 75, 5))+
facet_wrap(~ Region, ncol = 4)

将图形储存在变量中

ggplot2可以将图形存储在变量中,然后继续往这个变量中添加新的函数,如下所示:

1
2
gg1 <- ggplot(obama_vs_mccain, aes(Income, Turnout)) +
geom_point()

如果要显示其输出,直接输入print(gg1)gg1即可:

1
print(gg1)

或者是继续往里面添加函数,如下所示:

1
2
3
4
5
6
gg1 <- ggplot(obama_vs_mccain, aes(Income, Turnout)) +
geom_point()
gg2 <- gg1 +
facet_wrap(~ Region, ncol = 5) +
theme(axis.text.x = element_text(angle = 30, hjust =1))
gg2

绘制线图

现在使用ggplot2来绘制一下线图,使用的数据是learningr包中的crab_tag数据集,这个数据集记录了2008年和2009年,蟹类的迁移深度与温度。

1
2
library(learningr)
ggplot(crab_tag$daylog, aes(Date, -Min.Depth))+ geom_line()

在绘制多条线条时有一点复杂,当在ggplot中指定aesthetics时,用户是为所有的geom都指定了这个aesthetics,也就是说,aesthetics对绘图的影响来说是“全局的”,在下面的案例中,我们希望在一条线上指定最大深度,在另外一条线上指定最小深度,代码如下所示:

1
2
3
ggplot(crab_tag$daylog, aes(Date, -Min.Depth))+
geom_line(aes(y = -Max.Depth))+
geom_line(aes(y = -Min.Depth))

而在实际操作中,通常不采用这种方法,而是使用reshape2包中的melt函数处理一下数据,如下所示:

1
2
3
4
5
6
7
8
library(reshape2)
crab_long <- melt(
crab_tag$daylog,
id.vars = "Date",
measure.vars = c("Min.Depth","Max.Depth")
)
ggplot(crab_long, aes(Date, -value, group=variable))+
geom_line()

再来查看一下原始数据与经melt处理后的数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
> head(crab_tag$daylog)
Mission.Day Date Max.Temp Min.Temp Max.Depth Min.Depth Batt.Volts
1 0 2008-08-08 27.734 25.203 0.06 -0.07 3.06
2 1 2008-08-09 25.203 23.859 0.06 -0.07 3.09
3 2 2008-08-10 24.016 23.500 -0.07 -0.10 3.09
4 3 2008-08-11 26.453 23.281 -0.04 -0.10 3.09
5 4 2008-08-12 27.047 23.609 -0.10 -0.26 3.09
6 5 2008-08-13 24.625 23.438 -0.04 -0.13 3.09
> head(crab_long)
Date variable value
1 2008-08-08 Min.Depth -0.07
2 2008-08-09 Min.Depth -0.07
3 2008-08-10 Min.Depth -0.10
4 2008-08-11 Min.Depth -0.10
5 2008-08-12 Min.Depth -0.26
6 2008-08-13 Min.Depth -0.13

第二修改后的图形还不好看,因为两条线颜色是相同的,我们可以使用geom_ribbon来美化一下,使最大值与最小值之间进行填充,如下所示:

1
2
ggplot(crab_tag$daylog, aes(Date, ymin = -Min.Depth, ymax = -Max.Depth))+
geom_ribbon(color = "black", fill="white")

绘制直方图

这里还用learningr包中的obama_vs_mccain数据集,如下所示:

1
2
ggplot(obama_vs_mccain, aes(Obama))+
geom_histogram(binwidth = 5)

通过传递特殊的名字,例如..count....density..y-aesthetic中来可以计数或密度,现在我们使用..density..参数,注意看y轴的坐标:

1
2
ggplot(obama_vs_mccain, aes(Obama, ..density..))+
geom_histogram(binwidth = 5)

箱线图

1
2
3
4
5
6
7
ovm <- within(
obama_vs_mccain,
Region <- reorder(Region, Obama, median)
)
head(ovm)
ggplot(ovm, aes(Region, Obama))+
geom_boxplot()

条形图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
ovm <- within(
obama_vs_mccain,
Region <- reorder(Region, Obama, median)
)
ovm <- ovm[!(ovm$State %in% c("Alaska", "Hawaii")), ]
religions <- with(ovm, rbind(Catholic, Protestant, Non.religious, Other))
religions_long <- melt(
ovm,
id.vars = "State",
measure.vars = c("Catholic", "Protestant", "Non.religious", "Other")
)
ggplot(religions_long, aes(State, value, fill = variable)) +
geom_bar(stat = "identity") +
coord_flip()

参考资料

  1. 学习R.[美] Richard,Cotton 著刘军 译